home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * main.HexDumpDA.c
- *
- * HexDump is a DA that displays the contents of a file in hex and ASCII,
- * intended as an example of how to write a desk accessory. Among other
- * things, it shows the structure of a DA, how a DA gets and responds to
- * events, and how a DA manages the menu bar.
- *
- * Steve Stein, Symantec Corp.
- *
- */
-
- #include <DeviceMgr.h>
- #include <WindowMgr.h>
- #include <MenuMgr.h>
- #include <EventMgr.h>
- #include <FileMgr.h>
- #include <ToolboxUtil.h>
- #include <StdFilePkg.h>
- #include <pascal.h>
-
- #include "HexDump.h"
-
- /* global variables */
-
- int already_open = 0; /* 1 -> DA is already open */
- DCtlPtr dce; /* device control entry */
- MenuHandle menu = 0L; /* handle for our menu */
- int menuID; /* our menu ID */
- WindowPtr wp = 0L; /* our window pointer */
- Cursor wait; /* a copy of the watch cursor */
-
- extern int fileRef; /* the refnum of the file we're showing */
- extern long fileSize; /* and the file's size (in bytes) */
- enum fork whichFork; /* which fork are we viewing? */
-
- extern Handle findBufH;
-
- /*
- * main program
- *
- * The first two arguments are the values passed in registers A0/A1
- * to an assembly-language desk accessory. The third argument is a
- * selector indicating which entry point was called.
- *
- * No assembly language is needed to write a desk accessory in
- * LightspeedC!
- *
- */
-
- main(p, d, n)
- cntrlParam *p; /* ==> parameter block */
- DCtlPtr d; /* ==> device control entry */
- int n; /* entry point selector */
- {
- /* if dCtlStorage is nil then our storage wasn't allocated... */
-
- if (d->dCtlStorage == 0) { /* we must abort */
- if (n == 0) { /* if request is "open" */
- SysBeep(3); /* beep, then close the DA */
- CloseDriver(d->dCtlRefNum);
- }
- return(0); /* goodbye */
- }
-
- dce = d; /* copy the DCE ptr into our globals */
- dce->dCtlFlags &= ~dCtlEnable; /* we are not re-entrant */
-
- switch (n) { /* handle request: */
- case 0: /* open */
- doOpen();
- break;
- case 2: /* control */
- doControl(p->csCode, p->csParam);
- break;
- case 4: /* close */
- doClose();
- break;
- default: ;
- }
-
- dce->dCtlFlags |= dCtlEnable; /* enable control calls once more */
- return(0); /* we are done */
- }
-
- /*
- * doOpen - initialize DA
- *
- * This routine is called each time the DA is selected from the Apple
- * menu, even if it is already open. We need to make sure to go
- * through our initialization the first time only, so we use a (global)
- * flag "already_open" to keep track.
- *
- * However, the Device Manager resets the "dCtlFlags", "dCtlMenu",
- * "dCtlDelay", and "dCtlEMask" fields of the device control entry
- * from the corresponding fields of the device header each time the
- * desk accessory is opened, EVEN IF IT ALREADY OPEN. Therefore we
- * must set these fields to their proper values each time.
- *
- * We have to set the dNeedGoodBye flag so that we can close the file
- * we're viewing if the application quits out from under us.
- */
-
- doOpen()
- {
-
- /* every time ... */
-
- dce->dCtlFlags |= dNeedLock|dNeedGoodBye;
- if (wp)
- SelectWindow(wp); /* bring our window front */
- if (already_open) {
- dce->dCtlMenu = menuID; /* set the menu id */
- return;
- }
-
- /* first time only ... */
- /* do some global initialization */
- /* Create our menu */
- /* Create our window */
- /* Open a file */
-
- Get_Wait_Cursor();
- already_open = 1;
-
- Create_Menu();
- Create_Window();
-
- HiliteMenu( dce->dCtlMenu ); /* to simulate "open" menu selection */
- if (!doOpenFile()) { /* if user cancels, close HexDump */
- CloseDriver(dce->dCtlRefNum); /* Quit */
- return;
- };
- HiliteMenu(0);
-
- if (!Init_Find()) /* Init_Find will fail if there's not */
- /* enough memory for the find buffer */
- Disable_Find();
- }
-
- /*
- * doControl - handle DA actions
- *
- * This routine handles the DA actions that may be required. This
- * DA must respond to two control actions: menu selections and events.
- * In addition, this routine can also handle the "goodbye kiss" when
- * the application quits out from under the DA.
- *
- */
-
- doControl(code, parm)
- int code;
- int *parm;
- {
- switch (code) {
- case accMenu:
- doMenu(parm[1]);
- break;
- case accEvent:
- doEvent(*((EventRecord **)parm));
- break;
- case goodBye:
- doGoodBye();
- break;
- default: ;
- }
- if (code != accCursor) Update_Menu_Bar();
- }
-
- /*
- * doClose - clean up before being closed
- *
- */
-
- doClose()
- {
- Close_File( fileRef );
- DisposHandle( findBufH );
- DeleteMenu(dce->dCtlMenu);
- DrawMenuBar();
- dce->dCtlMenu = 0;
- DisposeMenu(menu);
- Destroy_Window();
- }
-
- /* Menu maintenance routines: */
-
- /*
- * Create_Menu
- *
- * Get our menu from the resource file, set dce->dCtlMenu,
- * insert the menu into the menu bar and draw the menu bar.
- */
-
- static
- Create_Menu()
- {
- dce->dCtlMenu = menuID = OwnedResourceID( MENUID );
- menu = GetMenu(menuID);
- (**menu).menuID = menuID;
- InsertMenu(menu = GetMenu(menuID), 0);
- DrawMenuBar();
- }
-
- /*
- * Update_Menu_Bar - Manage the appearance of our menu in the menu bar
- *
- * Our menu should appear when the front window belongs to us.
- */
-
- static
- Update_Menu_Bar()
- {
- register WindowPeek wPtr = (WindowPeek) FrontWindow ();
-
- if (wPtr) { /* there should always be a window, but we'll check. */
- if ( wPtr->windowKind == dce->dCtlRefNum ) {
- if (!GetMHandle (dce->dCtlMenu)) {
- InsertMenu (menu, 0);
- DrawMenuBar ();
- }
- }
- else if (GetMHandle (dce->dCtlMenu)) {
- DeleteMenu (dce->dCtlMenu);
- DrawMenuBar ();
- }
- }
- }
-
- static
- Disable_Find()
- {
- /* we had no memory for the find buffer */
- DisableItem(menu, FIND);
- DisableItem(menu, FINDAGAIN);
- }
-
- static
- Set_Fork(option)
- enum fork option;
- {
- whichFork = option;
- if (option==data) {
- CheckItem( menu, DATAFORK, true );
- CheckItem( menu, RSRCFORK, false );
- }
- else {
- CheckItem( menu, DATAFORK, false );
- CheckItem( menu, RSRCFORK, true );
- }
- }
-
- /*
- * doMenu - process menu selection
- *
- */
-
- doMenu(i) /* the i-th menu item was selected */
- int i;
- {
- switch (i) {
- case ABOUT: doAbout(); break;
- case OPEN: doOpenFile(); break;
- case DUMPTO: doDumpTo(); break;
- case DATAFORK: doOpenFork( data ); break;
- case RSRCFORK: doOpenFork( resource ); break;
- case FIND: doFind(); break;
- case FINDAGAIN: doFindAgain(); break;
- case GOTO: doGoto(); break;
- case QUIT:
- CloseDriver(dce->dCtlRefNum); /* close down the DA */
- return;
- }
- HiliteMenu(0);
- }
-
- static
- doOpenFork( f )
- enum fork f;
- {
- int newFileRef;
-
- if (f!=whichFork) {
- if (Open_Fork(f, &newFileRef)) {
- New_Open_File( newFileRef );
- Set_Fork(f);
- }
- else
- ErrorStr("\pCan't open fork.");
- }
- }
-
- static
- doOpenFile()
- {
- char *fileName;
- int vRef;
- enum fork option;
- int newFileRef;
-
- do {
- if (!oldfilename(&option ))
- return 0;
- } while (!Open_Fork(option, &newFileRef));
- New_Open_File( newFileRef );
- Set_Fork(option);
- return 1;
- }
-
- /*
- * TestWindowRgn uses the window's WDEF proc to sort out mouse hits.
- * In an application, FindWindow does this for you. In a DA, you
- * must do it yourself.
- */
-
- static
- Boolean TestWindowRgn(wp,p,msg)
- WindowPtr wp;
- Point p;
- int msg;
- {
- ProcPtr wDef;
-
- wDef = (ProcPtr) *((WindowPeek)wp) -> windowDefProc;
- return(CallPascalL( 8, wp, (int) wHit, p, wDef )==msg);
- }
-
- doMouse(p)
- Point p;
- {
- if (TestWindowRgn(wp, p, wInGrow))
- doGrow(p);
- else if (TestWindowRgn(wp, p, wInZoomIn))
- doZoom(p, inZoomIn);
- else if (TestWindowRgn(wp, p, wInZoomOut))
- doZoom(p, inZoomOut);
- else
- doScrollControl(p);
- }
-
- doCmdKey(c)
- char c;
- {
- int code;
- switch (c) {
- case 'o':
- case 'O': code = OPEN; break;
- case 'd':
- case 'D': code = DUMPTO; break;
- case 'f':
- case 'F': code = FIND; break;
- case 'a':
- case 'A': code = FINDAGAIN; break;
- case 'g':
- case 'G': code = GOTO; break;
- case 'q':
- case 'Q': code = QUIT; break;
- default : SysBeep(10); return;
- }
- HiliteMenu( dce->dCtlMenu );
- doMenu( code );
- }
-
- /*
- * doEvent is the DA's event handler.
- */
-
- doEvent(e)
- EventRecord *e;
- {
- switch (e->what) {
- case updateEvt:
- doUpdate();
- break;
- case mouseDown:
- doMouse(e->where);
- break;
- case activateEvt:
- doActivate((Boolean)(e->modifiers & activeFlag));
- break;
- case keyDown:
- case autoKey:
- if ( e->modifiers & cmdKey )
- doCmdKey((char)(e->message & charCodeMask));
- else
- SysBeep(10);
- break;
- }
- }
-
-
- /*
- * doGoodBye - respond to "goodbye kiss"
- *
- * This is called by the system when the application quits while
- * the DA is still open. We need to close our file, so we have
- * requested a "goodbye kiss".
- *
- */
-
- doGoodBye()
- {
- Close_File(fileRef);
- }
-
- /* error handling: */
-
- ErrorStr(s)
- char *s;
- {
- ParamText(s,"","","");
- Alert( OwnedResourceID(ERROR_ALERT), 0L );
- doUpdate();
- }
-
- Error(err)
- {
- Str255 s;
-
- NumToString(err,s);
- ParamText("\pHexDump detected error, ID = ",s,"","");
- Alert( OwnedResourceID(ERROR_ALERT), 0L);
- doUpdate();
- }
-
- No_Error(err)
- {
- if (err==noErr) return true;
- Error(err);
- return false;
- }
-
- /* utility routines: */
-
- /* OwnedResourceID - Compute the resource ID of */
- /* a resource owned by this DA. */
-
- OwnedResourceID(n)
- {
- return( 0xC000 + ((~(dce->dCtlRefNum))<<5) + n );
- }
-
- /* Get_Wait_Cursor -
- * Load the variable "wait" with the watch cursor.
- * Dispose the resource's copy in memory if it wasn't already there.
- */
-
- Get_Wait_Cursor()
- {
- CursHandle h;
- Boolean dispose;
-
- SetResLoad(false);
- h = GetCursor(watchCursor);
- dispose = (GetHandleSize((Handle)h) == 0);
- SetResLoad(true);
- BlockMove(*(h=GetCursor(watchCursor)), &wait, sizeof( Cursor ));
- if (dispose) ReleaseResource((Handle)h);
- }
-
-